package com.alan.blue;

import org.junit.jupiter.api.Test;

import javax.bluetooth.*;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * 一个蓝牙通信的简易例子
 * @Auther: Alan liu
 * @Date: 2018/11/27 16:25
 * @Description: MyDiscoveryListener
 */
public class MyDiscoveryListener implements DiscoveryListener{

    private static Object lock=new Object();
    public ArrayList<RemoteDevice> devices;

    public MyDiscoveryListener() {
        devices = new ArrayList<RemoteDevice>();
    }

    LocalDevice local;

    StreamConnectionNotifier notifier;

    private static ExecutorService service = Executors.newCachedThreadPool();

    private UUID uuid = new UUID("0000110100001000800000805F9B34FB",false);

    /**
     * 开启一个蓝牙服务端
     */
    @Test
    public void startServer() {
        try {
            local = LocalDevice.getLocalDevice();

            if (!local.setDiscoverable(DiscoveryAgent.GIAC)) {
                System.out.println("请将蓝牙设置为可被发现");
            }
            System.out.println("BluetoothAddress:"+local.getBluetoothAddress());
            /**
             * 作为服务端，被请求
             */
//            String url = "btspp://localhost:" +  new UUID(80087355).toString() + ";name=RemoteBluetooth";
            String url = "btspp://localhost:" + uuid.toString()+ ";name=RemoteBluetooth";
            notifier = (StreamConnectionNotifier)Connector.open(url);
            AcceptThread acceptThread = new AcceptThread();
            service.submit(acceptThread);
            Thread.sleep(60000);
            setStopFlag(true);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * 给蓝牙服务端发送信息
     */
    @Test
    public void pcSendMsgExg() {
        MyDiscoveryListener listener =  new MyDiscoveryListener();
        try{
            LocalDevice localDevice = LocalDevice.getLocalDevice();
            DiscoveryAgent agent = localDevice.getDiscoveryAgent();
            agent.startInquiry(DiscoveryAgent.GIAC, listener);
            try {
                synchronized(lock){
                    lock.wait();
                }
            }catch (InterruptedException e) {
                e.printStackTrace();
                return;
            }
            System.out.println("Device Inquiry Completed. ");
            UUID[] uuidSet = new UUID[1];
            //服务端的uuid
            uuidSet[0]= uuid;

            int[] attrIDs =  new int[] {
                    0x0100 // Service name
            };
            for (RemoteDevice device : listener.devices) {
                String name = device.getFriendlyName(false);
                if("HUAWEI Mate 8-Alan".equals(name)){
                    agent.searchServices(attrIDs,uuidSet,device,listener);
                    try {
                        synchronized(lock){
                            lock.wait();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        return;
                    }
                    System.out.println("Service search finished.");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void deviceDiscovered(RemoteDevice btDevice, DeviceClass arg1) {
        String name;
        try {
            name = btDevice.getFriendlyName(false);
        } catch (Exception e) {
            name = btDevice.getBluetoothAddress();
        }
        devices.add(btDevice);
        System.out.println("device found: " + name);

    }

    @Override
    public void inquiryCompleted(int arg0) {
        synchronized(lock){
            lock.notify();
        }
    }

    @Override
    public void serviceSearchCompleted(int arg0, int arg1) {
        synchronized (lock) {
            lock.notify();
        }
    }

    @Override
    public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
        for (int i = 0; i < servRecord.length; i++) {
            String url = servRecord[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
            if (url == null) {
                continue;
            }
            DataElement serviceName = servRecord[i].getAttributeValue(0x0100);
            if (serviceName != null) {
                System.out.println("service " + serviceName.getValue() + " found " + url);

                //这是在服务端的name Alan
                if(serviceName.getValue().toString().trim().equals("Alan")){
                    sendMessageToDevice(url);
                }
            } else {
                System.out.println("service found " + url);
            }
        }
    }


    private void sendMessageToDevice(String serverURL){
        try{
            System.out.println("Connecting to " + serverURL);
            StreamConnection streamConnection = (StreamConnection) Connector.open(serverURL);
            DataOutputStream dos = streamConnection.openDataOutputStream();
            dos.write("hello".getBytes());
            dos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 流连接
    private StreamConnection streamConnection = null;
    // 接受数据的字节流
    private byte[] acceptdByteArray = new byte[1024];
    // 输入流
    private DataInputStream inputStream;
    private Boolean stopFlag = false;

    public void setStopFlag(Boolean stopFlag) {
        this.stopFlag = stopFlag;
    }

    class AcceptThread implements Runnable{

        @Override
        public void run() {
            try {
                String inStr = null;
                //阻塞的，等待设备连接,这里就没有作中断处理了，如果没有连接该线程就无法关闭
                streamConnection = notifier.acceptAndOpen();
                inputStream = streamConnection.openDataInputStream();
                int length;
                while (true) {
                    //不阻塞线程
                    if ((inputStream.available()) <= 0) {
                        //关闭
                        if (stopFlag){
                            break;
                        }
                        //数据间隔比较长，手动堵塞线程
                        Thread.sleep(800);
                    } else {
                        length = inputStream.read(acceptdByteArray);
                        if(length>0) {
                            inStr = new String(acceptdByteArray,0,length);
                            System.out.println(inStr);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                    if (streamConnection != null) {
                        streamConnection.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }

}
